package substr

// A Matcher decides a string, returning true if the string matches and false
//if not. A Matcher must not modify the string in any way.
type Matcher interface {
	Match([]byte) bool
}

func (s *S) filter(negate bool, p Matcher) {
	ln := len(s.Subs)
	w := 0 // w <= r
	for r := 0; r < ln; r++ {
		v := s.Subs[r]
		t := p.Match(s.Super[v[0]:v[1]])
		if negate {
			t = !t
		}
		if t {
			s.Subs[w] = v
			w++
		}
	}
	//zero after write head
	for i := w; i < ln; i++ {
		s.Subs[i] = nil
	}
	s.Subs = s.Subs[:w]
}

// Keep every substring for which the predicate returns true.
// The operation is inplace and returns itself for chaining.
func (s *S) Keep(p Matcher) *S {
	s.filter(false, p)
	return s
}

// Drop every substring for which the predicate returns true.
// The operation is inplace and returns itself for chaining.
func (s *S) Drop(p Matcher) *S {
	s.filter(true, p)
	return s
}
